package com.ruoyi.library.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.constant.DrawingConstants;
import com.ruoyi.common.core.constant.TwinConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.BeanCopyUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.library.api.params.DigitalTwinSpaceParams;
import com.ruoyi.library.api.query.DigitalTwinSpaceQuery;
import com.ruoyi.library.api.vo.DigitalTwinSpaceVO;
import com.ruoyi.library.domain.DtsDigitalTwinSpace;
import com.ruoyi.library.mapper.DtsDigitalTwinSpaceMapper;
import com.ruoyi.library.service.IDtsDigitalTwinSpaceService;
import com.ruoyi.system.api.RemoteDictDataService;
import com.ruoyi.system.api.vo.SysDictDataVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 空间信息
 *
 * @author ZhangYu
 * @date 2024/05/20
 */
@Slf4j
@Service
public class DtsDigitalTwinSpaceServiceImpl extends ServiceImpl<DtsDigitalTwinSpaceMapper, DtsDigitalTwinSpace> implements IDtsDigitalTwinSpaceService {

    @Resource
    private RemoteDictDataService remoteDictDataService;
    @Resource
    private RedisService redisService;

    /**
     * 空间编码前缀
     */
    private static final String SPACE_CODE_PREFIX = "SPACE_CODE_";

    @Override
    public void addSpaceInfo(DigitalTwinSpaceParams digitalTwinSpaceParams) {
        DtsDigitalTwinSpace digitalTwinSpace = BeanCopyUtils.copyNewBean(digitalTwinSpaceParams, DtsDigitalTwinSpace.class);
        digitalTwinSpace.setSpaceCode(createSpaceCode());
        baseMapper.insert(digitalTwinSpace);
    }

    /**
     * 创建空间编码 如：SPACE_CODE_00001
     *
     * @return 空间编码
     */
    private synchronized String createSpaceCode() {
        String key = TwinConstants.SPACE_CODE_KEY;
        if (redisService.hasKey(key)) {
            log.info("--------------------------------------------------------------------------------空间编码存在redis中");
            Integer number = redisService.getCacheObject(key);
            redisService.setCacheObject(key, ++number, DrawingConstants.EXPIRATION_TIME, TimeUnit.MINUTES);
            return SPACE_CODE_PREFIX + String.format("%05d", number);
        }
        String maxSpaceCode = baseMapper.getMaxSpaceCode();
        if (StrUtil.isNotEmpty(maxSpaceCode)) {
            log.info("--------------------------------------------------------------------------------空间编码存在数据库中");
            String oldNumber = maxSpaceCode.substring(maxSpaceCode.length() - 5);
            int newNumber = Integer.parseInt(oldNumber);
            redisService.setCacheObject(key, ++newNumber, DrawingConstants.EXPIRATION_TIME, TimeUnit.MINUTES);
            return SPACE_CODE_PREFIX + String.format("%05d", newNumber);
        }
        log.info("----------------------------------------------------------------------------空间编码数据库、redis都不存在");
        redisService.setCacheObject(key, 1, DrawingConstants.EXPIRATION_TIME, TimeUnit.MINUTES);
        return SPACE_CODE_PREFIX + String.format("%05d", 1);
    }

    @Override
    public DigitalTwinSpaceVO getSpaceInfo(Long id) {
        return baseMapper.getSpaceInfo(id);
    }

    @Override
    public Page<DigitalTwinSpaceVO> spaceInfoPage(DigitalTwinSpaceQuery digitalTwinSpaceQuery) {
        Page<DigitalTwinSpaceVO> spaceInfoPage = baseMapper.spaceInfoPage(new Page<>(digitalTwinSpaceQuery.getPageNum(), digitalTwinSpaceQuery.getPageSize()), digitalTwinSpaceQuery);
        setDictDataByDictValueList(spaceInfoPage);
        return spaceInfoPage;
    }

    /**
     * 设置字典信息
     *
     * @param spaceInfoPage 空间信息分页
     */
    private void setDictDataByDictValueList(Page<DigitalTwinSpaceVO> spaceInfoPage) {
        List<DigitalTwinSpaceVO> digitalTwinSpaceList = spaceInfoPage.getRecords();
        if (CollectionUtil.isEmpty(digitalTwinSpaceList)) {
            return;
        }
        List<String> spaceTypeList = digitalTwinSpaceList.stream().map(DigitalTwinSpaceVO::getSpaceType).collect(Collectors.toList());
        R<List<SysDictDataVO>> sysDictDataListResult = remoteDictDataService.dictListByValue(spaceTypeList);
        List<SysDictDataVO> sysDictDataList = sysDictDataListResult.getData();
        for (DigitalTwinSpaceVO digitalTwinSpace : digitalTwinSpaceList) {
            SysDictDataVO sysDictData = sysDictDataList.stream().filter(sdd -> Objects.equals(sdd.getDictValue(), digitalTwinSpace.getSpaceType())).findFirst().orElseThrow(() -> new ServiceException("字典不存在"));
            digitalTwinSpace.setSpaceTypeLabel(sysDictData.getDictLabel());
        }
    }

}
